package cz.muni.fi.pb138.webrep.repositories;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */



import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.basex.core.BaseXException;
import org.basex.core.Context;
import org.basex.core.cmd.Close;
import org.basex.core.cmd.CreateDB;
import org.basex.core.cmd.Open;
import org.basex.core.cmd.XQuery;

/**
 *
 * @author Odin
 */
public class ArtifactRepository {
    private String artifactDBName;
    
    /**
     * Construct new instance of ArtifactRepository
     * 
     * @throws java.io.IOException
     * @throws org.basex.core.BaseXException
     */
    public ArtifactRepository() throws IOException {
        Properties p = new Properties();
        p.load(this.getClass().getResourceAsStream("../db_config.properties"));
        artifactDBName = p.getProperty("db.artifact.name");
        Context context = new Context();
        try {
            new Open(artifactDBName).execute(context);
        } catch(BaseXException e) {
            new CreateDB(artifactDBName, "<artifacts/>").execute(context);
        } finally {
            new Close().execute(context);
        }
    }
    
    /**
     * Adds record about new version of the artifact to database.
     * 
     * @param filename filename of the artifact
     * @throws org.basex.core.BaseXException
     */
    public void addArtifactRecord(String filename) throws BaseXException {
        filename = filename.replace("'", "&#39;");
        Context context = new Context();
        try {
            new Open(artifactDBName).execute(context);
            String query = "if (empty(/artifacts/artifact[@filename='"+ filename +"']))\n"
                    + "then insert node <artifact filename='"+ filename +"' />"
                    + " into /artifacts"
                    + " else ()";
            
            new XQuery(query).execute(context);
            query = "insert node <version/>"
                    + " into /artifacts/artifact[@filename='"+ filename +"']";
            new XQuery(query).execute(context);
        }
        finally {
            new Close().execute(context);
        }
    }
    
    /**
     * Returns number of versions of artifact with given filename
     * 
     * @param filename filename of the artifact
     * @return number of versions of artifact with given filename
     * @throws org.basex.core.BaseXException
     */
    public int getArtifactVersionsCount(String filename) throws BaseXException {
        filename = filename.replace("'", "&#39;");
        Context context = new Context();
        int result = 0;
        try {
            new Open(artifactDBName).execute(context);

            result = Integer.parseInt(
                    new XQuery("count(//artifact[@filename='"+ filename +"']/version)")
                        .execute(context)
                );
        }
        finally {
            new Close().execute(context);
        }
        return result;
    }
    /**
     * This method prepares and returns Map object, which contains
     * filenames of stored artifact as keys and for each key the value is
     * number of its stored versions.
     * 
     * @return Map where keys are filenames and values are counts of versions
     * @throws org.basex.core.BaseXException
     */
    public Map<String, Integer> getAllArtifactsAsMap() throws BaseXException {
        Context context = new Context();
        Map<String, Integer> map = new HashMap<>();
        try {
            new Open(artifactDBName).execute(context);

            String result = new XQuery("for $x in //artifact\n"
                + " order by $x/@filename\n"
                + " return concat('\"',$x/@filename, '\"/', count($x/version), '\n')")
                    .execute(context);
            // result seems like:"name",1\n "name2",1\n
            
            for(String artifactStr : result.split("\n")) {
                String artifactParts[] = artifactStr.split("/");
                if(artifactParts.length == 2) {
                    String filename = artifactParts[0].trim();
                    filename = filename.substring(1, filename.length()-1);
                    
                    String versionsCount = artifactParts[1].trim();
                    map.put(filename, Integer.parseInt(versionsCount));
                }
            }
        }
        finally {
            new Close().execute(context);
        }
        return map;
    }
    
    public void deleteVersionBecauseItsProcessingFailed(String artifactName) throws BaseXException {
        Context context = new Context();
        new Open(artifactDBName).execute(context);
        
        try {
            String result = new XQuery("delete node\n" +
                " //artifact[@filename = '"+ artifactName +"']/version[last()]")
                    .execute(context);
        }
        finally {
            new Close().execute(context);
        }
    }
    
    public void deleteArtifact(String artifactName) throws BaseXException {
        Context context = new Context();
        new Open(artifactDBName).execute(context);
        
        try {
            String result = new XQuery("delete node\n" +
                " //artifact[@filename = '"+ artifactName +"']")
                    .execute(context);
        }
        finally {
            new Close().execute(context);
        }
    }
}
